package ext.acae2.cad;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jcifs.smb.SmbFile;

import org.apache.log4j.Logger;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import wt.content.ApplicationData;
import wt.content.ContentHelper;
import wt.content.ContentItem;
import wt.content.ContentRoleType;
import wt.content.ContentServerHelper;
import wt.epm.EPMDocument;
import wt.epm.EPMDocumentMaster;
import wt.epm.EPMDocumentType;
import wt.epm.structure.EPMMemberLink;
import wt.epm.structure.EPMReferenceLink;
import wt.fc.PersistenceHelper;
import wt.fc.QueryResult;
import wt.fc.WTObject;
import wt.folder.Folder;
import wt.log4j.LogR;
import wt.method.RemoteAccess;
import wt.pds.StatementSpec;
import wt.pom.Transaction;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.session.SessionHelper;
import wt.session.SessionServerHelper;
import wt.util.WTException;
import wt.util.WTProperties;
import wt.vc.VersionControlHelper;
import wt.vc.struct.StructHelper;
import wt.vc.wip.CheckoutLink;
import wt.vc.wip.WorkInProgressHelper;
import ext.acae2.util.FileUtil;
import ext.acae2.util.UGHostUtil;
import ext.acae2.utilities.util.CSCUtil;

/**
 * @desription 二维图纸电子签名
 * @author cnie
 * @date 2013-7-17 下午8:39:56
 */
public class CADSignHelper implements RemoteAccess, Serializable {

	/**
	 * @description:TODO
	 */
	private static final long serialVersionUID = 1L;
	private static File tempCadFolder;
	private static final Logger LOGGER = LogR.getLogger(CADSignHelper.class.getName());

	static {
		try {
			String wttemp = WTProperties.getLocalProperties().getProperty(
					"wt.temp");
			tempCadFolder = new File(wttemp + File.separator + "cadsigntemp");
			
			if (!tempCadFolder.exists()) {
				tempCadFolder.mkdirs();
			}
			String wthome = WTProperties.getLocalProperties().getProperty("wt.home");
			UGHostUtil.execute(wthome + File.separator + "codebase"
					+ File.separator + "ext" + File.separator + "acae2"
					+ File.separator + "dms" + File.separator + "UGServer"
					+ File.separator + "UGHost.properties");
		} catch (Exception e) {

			e.printStackTrace();
		}
	}

	private static String getFileFromInputStream(InputStream fileInputStream,
			String filepath, String filename) throws Exception {
		String path = filepath + File.separator;
		File ff = new File(path, filename);
		byte[] buffer = new byte[10240];
		FileOutputStream fileOutputStream = new FileOutputStream(ff);
		while (true) {
			if (fileInputStream.available() < 1024) {
				int remain = -1;
				while ((remain = fileInputStream.read()) != -1) {
					fileOutputStream.write(remain);
				}
				break;
			} else {
				fileInputStream.read(buffer);
				fileOutputStream.write(buffer);
			}
		}
		fileInputStream.close();
		fileOutputStream.close();
		return path + filename;
	}

	public static EPMDocument getEPMDocumentByNumber(String epmNumber) {
		EPMDocument epm = null;
		String user = "";
		try {
			user = wt.session.SessionHelper.manager.getPrincipal().getName();
			wt.session.SessionHelper.manager.setAdministrator();
		} catch (Exception e) {
		}
		try {
			QuerySpec qs = new QuerySpec(EPMDocument.class);
			SearchCondition sc = new SearchCondition(EPMDocument.class,
					EPMDocument.NUMBER, SearchCondition.EQUAL, epmNumber, false);
			qs.appendWhere(sc, new int[] { 0 });
			QueryResult qr = PersistenceHelper.manager.find((StatementSpec) qs);
			if (qr.hasMoreElements()) {
				EPMDocument epmdocument = (EPMDocument) qr.nextElement();
				QueryResult qr2 = VersionControlHelper.service
						.allIterationsOf(epmdocument.getMaster());
				if (qr2.hasMoreElements()) {
					epm = (EPMDocument) qr2.nextElement();
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		if (!"".equals(user)) {
			try {
				wt.session.SessionHelper.manager.setPrincipal(user);
			} catch (Exception e) {
			}
		}
		return epm;
	}
	
	
	private static void getEPMDocumentStruct(EPMDocument epm,boolean isFirst,List<EPMDocument> epmdocuments) throws WTException{

		EPMDocument module3D = epm;
		if(!epmdocuments.contains(module3D)){
			epmdocuments.add(module3D);
		}
		
		if (isFirst) {
			QueryResult refQr = PersistenceHelper.manager.navigate(epm,
					EPMReferenceLink.REFERENCES_ROLE, EPMReferenceLink.class,
					false);
			while (refQr.hasMoreElements()) {
				EPMReferenceLink epmLink = (EPMReferenceLink) refQr
						.nextElement();
				if (epmLink.isRequired() && epmLink.getDepType() == 4) {

					EPMDocumentMaster epmdocumentMaster = (EPMDocumentMaster) epmLink
							.getReferences();
					QueryResult qr2 = VersionControlHelper.service
							.allIterationsOf(epmdocumentMaster);
					if (qr2.hasMoreElements()) {
						module3D = (EPMDocument) qr2.nextElement();
						if (!epmdocuments.contains(module3D))
							epmdocuments.add(module3D);
					}
				}
			}
		}
		 QueryResult qr1 = PersistenceHelper.manager.navigate(module3D.getMaster(),EPMReferenceLink.REFERENCED_BY_ROLE, EPMReferenceLink.class, false);
		 while(qr1.hasMoreElements())
         {
              EPMReferenceLink epmLink = (EPMReferenceLink)qr1.nextElement();
              WTObject wtObject = (WTObject)epmLink.getReferencedBy();
              if(wtObject instanceof EPMDocument){
            	  EPMDocument model2D = (EPMDocument)wtObject;
            	  model2D = getEPMDocumentByNumber(model2D.getNumber());
            	  if(!epmdocuments.contains(model2D)){
            		  epmdocuments.add(model2D);
            	  }
              }
         }
		 
		 QueryResult memlinkQr = StructHelper.service.navigateUses(module3D, EPMMemberLink.class, false);
		 while(memlinkQr.hasMoreElements()){
			 EPMMemberLink epmLink = (EPMMemberLink)memlinkQr.nextElement();
			 EPMDocumentMaster epmdocumentMaster = (EPMDocumentMaster) epmLink.getUses();
			 QueryResult qr2 = VersionControlHelper.service
						.allIterationsOf(epmdocumentMaster);
				if (qr2.hasMoreElements()) {
					EPMDocument childEpm = (EPMDocument) qr2.nextElement();
					if(!epmdocuments.contains(childEpm)){
						epmdocuments.add(childEpm);
					}
					getEPMDocumentStruct(childEpm,false,epmdocuments);
				}
		 }
	}
	
	
	/**
	 * 
	 * @description 单个二维图纸的签名的处理，替换主内容，返回产生的pdf文件的
	 * @author cnie
	 * @date 2013-8-9 下午3:29:08
	 * @version 1.0
	 * @param epmdocument 
	 * @param signInfo
	 * @param erroList
	 * @return
	 * @throws Exception
	 */
	public static String signCAD(EPMDocument epmdocument,
			Map<String, String> signInfo,List<String> errorList) throws Exception {
		String replaceFileStr = null;
		boolean enforced = SessionServerHelper.manager.setAccessEnforced(false);
/*		if (WorkInProgressHelper.isCheckedOut(epmdocument)) {
			if (!WorkInProgressHelper.isWorkingCopy(epmdocument))
				epmdocument = (EPMDocument) WorkInProgressHelper.service
						.workingCopyOf(epmdocument);
		} else {
			Folder checkoutFolder = WorkInProgressHelper.service
					.getCheckoutFolder();
			CheckoutLink checkoutlink = WorkInProgressHelper.service.checkout(
					epmdocument, checkoutFolder, "forCADSign");
			epmdocument = (EPMDocument) checkoutlink.getWorkingCopy();
		}*/
//		PersistenceHelper.manager.lockAndRefresh(epmdocument);
		List<EPMDocument> epmdocuments = new ArrayList<EPMDocument>();
//		getEPMDocumentStruct(epmdocument, true, epmdocuments);
		epmdocuments.add(epmdocument);
		for (EPMDocument epm : epmdocuments) {
			System.out.println(epm.getNumber() + ":::" + epm.getName() + ":::"
					+ epm.getVersionIdentifier().getValue() + "::::"
					+ epm.getIterationIdentifier().getValue());
			LOGGER.debug(epm.getNumber() + ":::" + epm.getName() + ":::"
					+ epm.getVersionIdentifier().getValue() + "::::"
					+ epm.getIterationIdentifier().getValue());
		}

		String prtModelPath = null;  //cadname创建的子文件
		File tempPrtFolder = null;   //下载cad主内容直接存放目录
		String signprimaryFileName = null; 
		ApplicationData signAppData = null;
		String currentUserName = SessionHelper.manager.getPrincipal().getName();
		/************ 下載主要內容 begin ***************/
		for (EPMDocument epm : epmdocuments) {
			QueryResult qr = ContentHelper.service.getContentsByRole(
					epm, ContentRoleType.PRIMARY);
			if (qr.hasMoreElements()) {
				ContentItem contentItem = (ContentItem) qr.nextElement();
				if (contentItem instanceof ApplicationData) {
					ApplicationData appData = (ApplicationData) contentItem;
					String primaryFileName = appData.getFileName();
					if (primaryFileName.indexOf("CAD_NAME") > -1) {
						primaryFileName = epm.getCADName();
					}

					InputStream is = ContentServerHelper.service
							.findContentStream(appData);
					if (epmdocument.equals(epm)) {
						signprimaryFileName = primaryFileName;
						prtModelPath = primaryFileName.substring(0,
								primaryFileName.lastIndexOf("."));
						String prttempFolder = tempCadFolder.getAbsolutePath()+File.separator+currentUserName
								+ File.separator + prtModelPath;
						tempPrtFolder = new File(prttempFolder); // 最中的prt临时文件
						if (!tempPrtFolder.exists()) {
							tempPrtFolder.mkdirs();
						}
						signAppData = appData;
						signInfo.put("modelName", UGHostUtil.UGSERVERTEMP
								+ "cadSign\\"+currentUserName+"\\" + prtModelPath + "\\"
								+ primaryFileName);
					}
					String tempFileName = getFileFromInputStream(is,
							tempPrtFolder.getAbsolutePath(), primaryFileName);
				}
			}
		}
		/************ 下載主要內容 end ***************/
		String ugServerPath = UGHostUtil.UGTEMPSMB + "cadSign/" +currentUserName+"/"+ prtModelPath
				+ "/";
		try{
			/************* UG CAD签名接口 begin ***************/
			
			System.out.println("serverPath>>>>>>>>>>>>>>>>" + ugServerPath);
			boolean isupload = UGServerHelper.uploadPrimaryFileToUGServer(
					tempPrtFolder, ugServerPath); // 上传文件到UG服务器
			if (!isupload) {
				errorList.add("二维图纸的编号:"+epmdocument.getNumber()+" 主内容上传失败");
				throw new Exception("file upload failure");
			}
			
			boolean isdelete = FileUtil.deleteDir(tempPrtFolder);
			if(isdelete){
				tempPrtFolder = new File(tempCadFolder.getAbsolutePath()+File.separator+currentUserName+File.separator+prtModelPath);
				tempPrtFolder.mkdirs();
			}

			boolean signFlag = UGServerHelper.invokeUGServer(signInfo,
					UGHostUtil.UGCADHOST);

			if (!signFlag) {
				errorList.add("二维图编号:"+epmdocument.getNumber()+" 主内容在UG中签名失败");
				throw new Exception("cad primary sign failure");
			}

			boolean downloadFlag = UGServerHelper.downloadPrimaryFile(
					tempPrtFolder.getAbsolutePath(), ugServerPath);
			if (!downloadFlag) {
				errorList.add("二维图编号:"+epmdocument.getNumber()+" UG签名后的主内容下载失败");
				throw new Exception("cad primary download failure");
			}
			
			FileUtil.delAllFile(ugServerPath);
			SmbFile myFilePath = new SmbFile(ugServerPath);
			if(myFilePath.exists())
				myFilePath.delete();
			/************* UG CAD签名接口 end ***************/
			
			/**************更新 CAD primary file begin***************/
			File signedFile = new File(tempPrtFolder.getAbsolutePath()
					+ File.separator + signprimaryFileName);
			ContentServerHelper.service.deleteContent(epmdocument, signAppData);
			FileInputStream fis = new FileInputStream(signedFile);
			ApplicationData newapplicationdata = ApplicationData
					.newApplicationData(epmdocument);
			newapplicationdata.setFileName(signprimaryFileName);
			newapplicationdata.setRole(ContentRoleType.PRIMARY);
			newapplicationdata = ContentServerHelper.service.updateContent(
					epmdocument, newapplicationdata, fis);
			fis.close();

			if (WorkInProgressHelper.isCheckedOut(epmdocument)) {
				WorkInProgressHelper.service.checkin(epmdocument, "forCADSign");
			}
			LOGGER.debug("signprimaryFileName>>>>>>>>>>>>>"+signprimaryFileName+".pdf");
			/**************更新 CAD primary file end***************/
			errorList.add("二维图编号："+epmdocument.getNumber()+" <font style=\"color:green\">主内容签名替换成功</font>");
			replaceFileStr = tempPrtFolder.getAbsolutePath()+File.separator+signprimaryFileName+".pdf";
		}catch(Exception e){
			//replaceFileStr = tempPrtFolder.getAbsolutePath();
			throw new Exception(e.getMessage());
		}finally{
			SessionServerHelper.manager.setAccessEnforced(enforced);
			if (WorkInProgressHelper.isCheckedOut(epmdocument)) {
				WorkInProgressHelper.service.undoCheckout(epmdocument);
			}
//			if(tempPrtFolder.exists())
//				FileUtil.deleteDir(tempPrtFolder);
			FileUtil.delAllFile(ugServerPath);
			SmbFile myFilePath = new SmbFile(ugServerPath);
			if(myFilePath.exists())
				myFilePath.delete();
		}
		return replaceFileStr;
	}
	
	/***
	 * 
	 * @description signCAD的入口
	 * @author cnie
	 * @date 2013-8-9 下午3:23:25
	 * @version 1.0
	 * @param epmSignMap  Map<EpmDocument,Map<String,String> signInfo
	 * @param errorList 错误信息
	 * @param isNew 代表是否是历史数据的处理 false:代表是历史数据的处理
	 */
	public static void signCADSOverride(Map<EPMDocument,Map<String,String>> epmSignMap,List<String> errorList,boolean isNew){
		
		Transaction trans = null;
		File tempPrtFolder = null;
		try {
			trans = new Transaction();
			trans.start();
			for (java.util.Iterator<EPMDocument> epmIt = epmSignMap.keySet()
					.iterator(); epmIt.hasNext();) {
				EPMDocument epmdocument = epmIt.next();
				Map<String, String> signInfo = epmSignMap.get(epmdocument);
				String pdfReplaceFileStr = signCAD(epmdocument, signInfo,errorList);
				LOGGER.debug("<<<<<pdfReplaceFile is null>>>>>>>>>>>>>"+(pdfReplaceFileStr==null));
				LOGGER.debug("<<<<<pdfReplaceFile>>>>>>>>>>>>>"+pdfReplaceFileStr);
				if(isNew)   //是否需要替换可视化
					continue;
				
				if(pdfReplaceFileStr==null||!new File(pdfReplaceFileStr).exists()||new File(pdfReplaceFileStr).length()==0){
					errorList.add("二维图编号："+epmdocument.getNumber()+" <font style=\"color:red\">没有产生签名的pdf文件,可视化文件没有替换，附件没有替换,需要重新处理</font>");
					continue;
				}
				File pdfReplaceFile = new File(pdfReplaceFileStr);
				tempPrtFolder = new File(pdfReplaceFileStr.substring(0,pdfReplaceFileStr.lastIndexOf(File.separator)));
					
				epmdocument = (EPMDocument) PersistenceHelper.manager.refresh(epmdocument);
//				boolean replaceFlag  = RepresentationReplace.replaceRepresentationPdf(epmdocument, pdfReplaceFile);
//				if(replaceFlag)
//					errorList.add("二维图编号："+epmdocument.getNumber()+" <font style=\"color:green\">可视化PDF替换成功</font>");
//				else
//					errorList.add("二维图编号："+epmdocument.getNumber()+" <font style=\"color:red\">可视化PDF替换失败</font>");
				
//				if(pdfReplaceFile!=null){
//					/**************更新 CAD second file begin*****************/
//					QueryResult secondQr = ContentHelper.service.getContentsByRole(epmdocument, ContentRoleType.SECONDARY);
//					while(secondQr.hasMoreElements()){
//						ContentItem secondCi = (ContentItem)secondQr.nextElement();
//						if(!(secondCi instanceof ApplicationData))
//							continue;
//						ApplicationData secondAppData = (ApplicationData)secondCi;
//						if(secondAppData.getFileName().toUpperCase().endsWith(".PDF")){
//							ContentServerHelper.service.deleteContent(epmdocument, secondAppData);
//							FileInputStream newfis = new FileInputStream(pdfReplaceFile);
//							ApplicationData newsecondAppData = ApplicationData
//									.newApplicationData(epmdocument);
//							newsecondAppData.setFileName(secondAppData.getFileName());
//							newsecondAppData.setRole(ContentRoleType.SECONDARY);
//							newsecondAppData = ContentServerHelper.service.updateContent(
//									epmdocument, newsecondAppData, newfis);
//						}
//					}
//					errorList.add("二维图编号："+epmdocument.getNumber()+" <font style=\"color:green\">PDF附件替换成功</font>");
//					/**************更新 CAD second file end*****************/
//				}
			}
			trans.commit();
		} catch (Exception e) {
			e.printStackTrace();
			trans.rollback();
			errorList.clear();
			errorList.add("系统异常");
			//throw new Exception(e.getMessage());
		} finally {
			if(tempPrtFolder!=null&&tempPrtFolder.exists())
				FileUtil.deleteDir(tempPrtFolder);
			if (trans != null) {
				trans = null;
			}
		}
//		return errorList;
	}

	/***
	 * 
	 * @description CAD 签名信息的入口
	 * @author cnie
	 * @date 2013-7-17 下午10:51:56
	 * @version 1.0
	 * @param epmSignMap
	 * @throws Exception 
	 */
	public static List<String> signCADS(Map<String, Map<String, String>> epmSignMap) throws Exception {
		List<String> errorList = new ArrayList<String>();
		Transaction trans = null;
		try {
			trans = new Transaction();
			trans.start();
			for (java.util.Iterator<String> epmIt = epmSignMap.keySet()
					.iterator(); epmIt.hasNext();) {
				String epmnumber = epmIt.next().trim();
				EPMDocument epmdocument = CADSignHelper.getEPMDocumentByNumber(epmnumber);
				if(epmdocument==null){
					errorList.add("(ERROR):"+epmnumber+" epmdocument is not exit");
				}
				if(!EPMDocumentType.toEPMDocumentType("CADDRAWING").equals(epmdocument.getDocType())){
					errorList.add("(ERROR):"+epmnumber+" epmdocument is not CAD");
				}
				Map<String, String> signInfo = epmSignMap.get(epmnumber);
				signCAD(epmdocument, signInfo,errorList);
			}
			trans.commit();
		} catch (Exception e) {
			e.printStackTrace();
			trans.rollback();
			throw new Exception(e.getMessage());
		} finally {
			if (trans != null) {
				trans = null;
			}
		}
		return errorList;
	}
	/**
	 * 
	 * @description 读取SignInfo的xml文件
	 * @author cnie
	 * @date 2013-7-19 上午9:37:29
	 * @version 1.0
	 * @param signInfoXmlPath
	 * @throws Exception 
	 */
	public static Map<String, Map<String,String>> readSignInfoFormXML(String signInfoXmlPath) throws Exception{
		File file = new File(signInfoXmlPath);
		if(!file.exists()){
			System.out.println("(ERROR):file is not exit:"+signInfoXmlPath);
			LOGGER.debug("(ERROR):file is not exit:"+signInfoXmlPath);
			return null;
		}
		org.dom4j.Document doc = new SAXReader().read(file);
		Element rootEl = doc.getRootElement();
		if(!"CADSignInfo".equals(rootEl.getName())){
			System.out.println("(ERROR):xml format is not right,the root element name is:CADSignInfo,not :"+rootEl.getName());
			LOGGER.debug("(ERROR):xml format is not right,the root element name is:CADSignInfo,not :"+rootEl.getName());
			return null;
		}
		Map<String, Map<String,String>> cadsignInfo  = new HashMap<String, Map<String,String>>();
		List<Element> childEls = rootEl.elements();
		for(java.util.Iterator<Element> childIt = childEls.iterator();childIt.hasNext();){
			Element childEl = childIt.next();
			String epmdoucment = childEl.attributeValue("cadNumber");
			if(epmdoucment!=null&&!"".equals(epmdoucment)){
				 Map<String,String> signInfo = new HashMap<String, String>();
				List<Element> infoEls = childEl.elements();
				for(java.util.Iterator<Element> infoIt = infoEls.iterator();infoIt.hasNext();){
					Element infoEl = infoIt.next();
					if(infoEl.attributeValue("name")!=null&&!"".equals(infoEl.attributeValue("name")))
						signInfo.put(infoEl.attributeValue("name"), infoEl.getTextTrim());
				}
				cadsignInfo.put(epmdoucment, signInfo);
			}
		}
		return cadsignInfo;
	}
	
	public static void main(String[] args) throws Exception {
		EPMDocument epm = (EPMDocument) CSCUtil.getObjectByOid("OR:wt.epm.EPMDocument:284957");
		List<EPMDocument> epmdocuments = new ArrayList<EPMDocument>();
		getEPMDocumentStruct(epm, true, epmdocuments);
	}

}
